//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

namespace Microsoft.Research.eResearch.Ontology.Lookup
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;

    /// <summary>
    /// This class implements <see cref="IOntologyLookupTable"/> interface and performs lookup from hardcoded values.
    /// </summary>
    public class HardCodedOntologyLookupTable : IOntologyLookupTable
    {
        /// <summary>
        /// Instance of the lookup table.
        /// </summary>
        private Dictionary<string, string> conceptLookupTable = new Dictionary<string, string>();

        /// <summary>
        /// Initializes a new instance of the HardcodedOntologyLookupTable class.
        /// </summary>
        public HardCodedOntologyLookupTable()
        {
            PopulateConceptLookupTable();
        }

        /// <summary>
        /// Performs lookup using the property qualified name.
        /// </summary>
        /// <param name="propertyQualifiedName">Property qualified name.</param>
        /// <returns>The concept name.</returns>
        public string MapPropertyToConcept(string propertyQualifiedName)
        {
            if (conceptLookupTable.ContainsKey(propertyQualifiedName))
            {
                return conceptLookupTable[propertyQualifiedName];
            }

            return null;
        }

        /// <summary>
        /// Performs lookup using the object type and property name.
        /// </summary>
        /// <param name="objectType">Type of the object.</param>
        /// <param name="propertyName">Name of the property.</param>
        /// <returns>The concept name.</returns>
        public string MapPropertyToConcept(Type objectType, string propertyName)
        {
            if (objectType == null)
            {
                return null;
            }

            string conceptName = MapPropertyToConcept(CreatePropertyQualifiedName(objectType, propertyName));
            if (conceptName == null)
            {
                conceptName = MapPropertyToConcept(objectType.BaseType, propertyName);
            }

            return conceptName;
        }

        // public List<ConceptValuePair> MapInstancePropertiesToConcepts(object input)
        // {
        //    List<ConceptValuePair> list = new List<ConceptValuePair>();
        //    Type objectType = input.GetType();
        //    foreach (PropertyInfo pi in objectType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
        //    {
        //        string conceptName = MapPropertyToConcept(objectType, pi.Name);
        //        if (conceptName == null)
        //        {
        //            conceptName = "ConceptNotDefined";
        //        }
        //        if (typeof(IEnumerable).IsAssignableFrom(pi.PropertyType))
        //        {
        //            IEnumerable collection = (IEnumerable)pi.GetValue(input, null);
        //            foreach (object collectionItem in collection)
        //            {
        //                list.Add(new ConceptValuePair(conceptName, collectionItem.ToString()));
        //            }
        //        }
        //        else
        //        {
        //            object propertyValue = pi.GetValue(input, null);                    
        //            list.Add(new ConceptValuePair(conceptName, propertyValue.ToString()));
        //        }
        //    }
        //    return list;
        // }

        /// <summary>
        /// Creates property qualified name from the type and property name.
        /// </summary>
        /// <param name="objectType">Type of the object.</param>
        /// <param name="propertyName">Name of the property.</param>
        /// <returns>Property qualified name.</returns>
        private static string CreatePropertyQualifiedName(Type objectType, string propertyName)
        {
            return String.Format(CultureInfo.CurrentUICulture, "{0}.{1}", objectType.FullName, propertyName);
        }

        /// <summary>
        /// Popluates the lookup table index from file store.
        /// </summary>
        private void PopulateConceptLookupTable()
        {
            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.TrackingRecord.EventDateTime", "time:DateTimeDescription");
            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.TrackingRecord.Annotations", "trident:Annotation");
            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.TrackingRecord.EventOrder", "trident:EventOrder");

            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.ActivityTrackingRecord.ActivityType", "trident:CLRType");
            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.ActivityTrackingRecord.ContextGuid", "trident:Guid");
            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.ActivityTrackingRecord.ExecutionStatus", "trident:ActivityState");
            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.ActivityTrackingRecord.ParentContextGuid", "trident:Guid");
            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.ActivityTrackingRecord.QualifiedName", "trident:ActivityName");
            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.ActivityTrackingRecord.Annotations", "trident:ActivityLabel");

            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.WorkflowTrackingRecord.TrackingWorkflowEvent", "trident:WorkflowState");

            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.UserTrackingRecord.ActivityType", "trident:CLRType");
            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.UserTrackingRecord.ContextGuid", "trident:Guid");
            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.UserTrackingRecord.ParentContextGuid", "trident:Guid");
            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.UserTrackingRecord.QualifiedName", "trident:ActivityName");
            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.UserTrackingRecord.UserData", "trident:UserData");
            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.UserTrackingRecord.UserDataKey", "trident:UserDataKey");
            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.UserTrackingRecord.IterationValue", "trident:IterationValue");
            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.UserTrackingRecord.DataProductID", "trident:DataProductID");
            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.UserTrackingRecord.Annotations", "trident:ActivityLabel");

            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.TrackingDataItem.Data", "trident:ActivityPropertyValue");

            // Note: System.Workflow.Runtime.Tracking.TrackingDataItem.DataType is not exists. But for the consistency purpose we added.
            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.TrackingDataItem.DataType", "trident:ActivityPropertyType");
            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.TrackingDataItem.FieldName", "trident:FieldName");
            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.TrackingDataItem.Annotations", "trident:ActivityPropertyDirection");

            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.TrackingParameters.CallerContextGuid", "trident:CallerContextGuid");
            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.TrackingParameters.CallerInstanceId", "trident:CallerInstanceId");
            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.TrackingParameters.CallerParentContextGuid", "trident:CallerParentContextGuid");
            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.TrackingParameters.ContextGuid", "trident:ContextGuid");
            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.TrackingParameters.InstanceId", "trident:InstanceId");
            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.TrackingParameters.WorkflowType", "trident:WorkflowType");

            // Note: System.Workflow.Runtime.Tracking.TrackingDataItem.OutputDataProductID is not exists. But for the consistency purpose we added.
            conceptLookupTable.Add("System.Workflow.Runtime.Tracking.TrackingDataItem.OutputDataProductID", "trident:OutputDataProductID");
        }
    }
}
